package com.kevinkk.dp;

/**
 * 给定一个 m x n 的整数数组 grid。一个机器人初始位于 左上角（即 grid[0][0]）。机器人尝试移动到 右下角（即 grid[m - 1][n - 1]）。机器人每次只能向下或者向右移动一步。
 * 网格中的障碍物和空位置分别用 1 和 0 来表示。机器人的移动路径中不能包含 任何 有障碍物的方格。
 * 返回机器人能够到达右下角的不同路径数量。
 */

/**
 * 1. 确定 dp 数组含义：
 *      dp[i][j] ：表示从（0 ，0）出发，到(i, j) 有dp[i][j]条不同的路径。
 * 2. 确定 dp 公式：
 *      dp[i][j] = dp[i - 1][j] + dp[i][j - 1]
 *      但是如果有障碍物的话 dp[i][j] = 0
 * 3. 初始化：
 *      从(0, 0)的位置到(i, 0)的路径只有一条，所以dp[i][0]一定为1，dp[0][j]也同理
 *      但是如果有障碍物的话 dp[i][j] = 0
 * 4. 确定遍历顺序：
 *      从递归公式dp[i][j] = dp[i - 1][j] + dp[i][j - 1] 中可以看出，一定是从左到右一层一层遍历
 *      这样保证推导dp[i][j]的时候，dp[i - 1][j] 和 dp[i][j - 1]一定是有数值
 */

public class UniquePathsII {
    class Solution {
        public int uniquePathsWithObstacles(int[][] obstacleGrid) {
            int m = obstacleGrid.length, n = obstacleGrid[0].length;
            int[][] dp = new int[m][n];

            for (int i = 0; i < n && obstacleGrid[0][i] == 0; i++)
                dp[0][i] = 1;
            for (int i = 0; i < m && obstacleGrid[i][0] == 0; i++)
                dp[i][0] = 1;

            for (int i = 1; i < m; i++) {
                for (int j = 1; j < n; j++) {
                    if (obstacleGrid[i][j] == 0) {
                        dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
                    } else {
                        dp[i][j] = 0;
                    }
                }
            }

            return dp[m - 1][n - 1];
        }
    }
}
